﻿

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using TrackSystem.IO.Data;
using TrackSystem.IO.Models;

namespace TrackSystem.IO.Protocol
{

    /// <summary>
    /// Seapath 42 通信协议 "71 <00 00 A2 87> <00 1C 61 25 38> <53 20 F5 E9> <00 00 0A 8C> <00 17> <00 25> <FF 0XEC> <00 2C> <F8 0X48> <FE 0XAD> <47 53> <07 D6> <0C 69> <F2 0XE4> <00 00> <59 52>"
    /// 0--hh 时间; hhmmss 格式
    /// 1--mm 分钟
    /// 2--ss 秒
    /// 3--纬度;
    /// 4--经度;
    /// 5--高度，单位厘米;
    /// 6--升沉，单位厘米;
    /// 7--北向速度，单位cm/s;
    /// 8--东向速度，单位cm/s;
    /// 9--垂直向速度，单位cm/s;
    /// 10--横滚角，单位90/2^14°;
    /// 11--俯仰角，单位90/2^14;
    /// 12--方位角，单位90/2^14;
    /// 13--横滚角速率，单位90/2^14°/s;
    /// 14--俯仰角速率，单位90/2^14°/s;
    /// 15--方位角速率，单位90/2^14°/s;
    /// 16--状态位 0: Reduced horizontal position, 1 invalid horizontal position, 2: Reduced heave, 3: Invalid heave, 4: Reduced roll, 5: Invalid roll, 6: Reduced heading, 7: Invalid heading
    /// </summary>
    public class Seapath42Protocol : ProtocolBase
    {
        private int startTicks;
        private bool bSendR;
        private int BeckIndex;
        private long lastDtTicks;

        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="name"></param>
        public Seapath42Protocol(string name)
            : base()
        {
            NeedInit = false;
            Name = name;
            bSendR = false;
            BeckIndex = 0;
            lastDtTicks = Environment.TickCount;   //DateTime.Now.Ticks;
        }

        /// <summary>
        /// 生成读取寄存器的通讯帧
        /// </summary>
        /// <returns></returns>
        public override byte[] GenerateReadFrame(out int NeedRecvLen)
        {
            startTicks = Environment.TickCount;
            if (bSendR)
            {
                Fail_R++;
                // 失败超过10次，成功次数清零
                if (Fail_R >= 10)
                {
                    Succ_R = 0;
                }
            }
            bSendR = true;
            NeedRecvLen = 16;
            return null;
        }

        /// <summary>
        /// 根据收到的内容进行处理
        /// </summary>
        /// <param name="buffer"></param>
        /// <returns></returns>
        public override bool ProcessReadFrame(byte[] buffer)
        {
            var DataFactory = RegFactory.Instance;
            Rx_r = buffer;  // 用于显示的接收帧内容
            
            Lapse = Environment.TickCount - startTicks;
            
            if (buffer[0] != 0x71)
            {
                return false;
            }
            
            
            if (buffer[0] == 0x71)
            {
                

                double total_seconds = (buffer[2] << 16 | buffer[3] << 8 | buffer[4]) * 1.0;
                int d1 = (int)(total_seconds / 60.0);
                double seconds = (int)((total_seconds / 60.0 - d1) * 60) + buffer[5] * 0.01;
                int hours = (int)(d1 / 60.0);
                int minutes = (int)((d1 / 60.0 - hours) * 60);

                double latitude = convertUint(buffer[6], buffer[7] , buffer[8], buffer[9]) * 90.0 / Math.Pow(2.0, 30);
                double longitude = convertUint(buffer[10] , buffer[11] , buffer[12], buffer[13]) * 90.0 / Math.Pow(2.0, 30);
                double altitude = convertUint(buffer[14], buffer[15], buffer[16], buffer[17]) * 0.01;
                
                int num = convertUshort(buffer[18], buffer[19]);
                double rise = num * 0.01;

                num = convertUshort(buffer[20] , buffer[21]);                
                double northv = num * 0.01;

                num = convertUshort(buffer[22], buffer[23]);
                double eastv = num * 0.01;

                num = convertUshort(buffer[24], buffer[25]);
                double vertv = num * 0.01;

                double roll = (convertUshort(buffer[26], buffer[27])) * 90.0 / Math.Pow(2.0, 14);
                double pitch = (convertUshort(buffer[28], buffer[29])) * 90.0 / Math.Pow(2.0, 14);
                double heading = ((buffer[30] << 8 | buffer[31])) * 90.0 / Math.Pow(2.0, 14);
                double rollrate = (convertUshort(buffer[32], buffer[33])) * 90.0 / Math.Pow(2.0, 14);
                double pitchrate = (convertUshort(buffer[34], buffer[35])) * 90.0 / Math.Pow(2.0, 14);
                double headingrate = (convertUshort(buffer[36], buffer[37])) * 90.0 / Math.Pow(2.0, 14);
                double status = (convertUshort(buffer[38], buffer[39])) * 1.0;
                
                DataFactory.SetVal(RegNameList[0], hours);
                DataFactory.SetVal(RegNameList[1], minutes);
                DataFactory.SetVal(RegNameList[2], seconds);
                DataFactory.SetVal(RegNameList[3], latitude);
                DataFactory.SetVal(RegNameList[4], longitude);
                DataFactory.SetVal(RegNameList[5], altitude);
                DataFactory.SetVal(RegNameList[6], rise);
                DataFactory.SetVal(RegNameList[7], northv);
                DataFactory.SetVal(RegNameList[8], eastv);
                DataFactory.SetVal(RegNameList[9], vertv);
                DataFactory.SetVal(RegNameList[10], roll);
                DataFactory.SetVal(RegNameList[11], pitch);
                DataFactory.SetVal(RegNameList[12], heading);
                DataFactory.SetVal(RegNameList[13], rollrate);
                DataFactory.SetVal(RegNameList[14], pitchrate);
                DataFactory.SetVal(RegNameList[15], headingrate);
                DataFactory.SetVal(RegNameList[16], status);
               



                Succ_R++;
                bSendR = false;     // 正确收到，标志位变为false
                Fail_R = 0;         // 通信成功，则将失败次数清零
            }


            return true;
        }

        private static int convertUshort(byte b1, byte b2)
        {
            var num = (b1 << 8 | b2);
            if (num > short.MaxValue) num = num - ushort.MaxValue -1;
            return num;
        }

        private static long convertUint(byte b1, byte b2, byte b3, byte b4)
        {
            long num = (b1 << 24 | b2 << 16 | b3 << 8 | b4);
            if (num > int.MaxValue) num = num - uint.MaxValue - 1;
            return num;
        }

    }
}
